#include "game.h"

#include <ctype.h>
#define BACKSPACE 8
#define ESC 27
#define DICT_SIZE 6 /* Change according to actual size of the dictionary array*/


/*
 * Dicionário de Palavras do Computador
 */
static SecretWord dictionary [DICT_SIZE] =  {{"Hamburger", "Algo que se come!"} ,
									{"Porto", "Cidade do Norte de Portugal!"},
							        {"Miranda" ,"Uma das cidades belas de Portugal"},
									{"Linux","O melhor sistema operativo"},
									{"NuIEEE","O melhor nucleo Academico"},
									{"Amesterdao","Veneza gelada do Norte"}
                                   };

extern int msec;
SecretWord generate_string( SecretWord * dictionary )
{
	int n = rand() % (DICT_SIZE);

	return dictionary[n];
}

int find_letter (char * word  , char letter , char * letters_used )
{
	int i= 0 , right = 0;

	while(letters_used[i] != '\0' &&  i < 27)
	{
		if(tolower( letters_used[i] )  == tolower(letter) )
			return -1;
		++i;
	}

	i = 0;
	while(word[i] != '\0')
	{
		if(tolower( word[i] )  == tolower(letter))
		{
			++right;
		}
		++i;
	}
	return right;
}

void update_word (int x_pos, int y_pos, int fore_color, int back_color,
		int char_scale, char* video_base, char* table, char * word , char letter)
{
	int i= 0;
	x_pos += 3;
	while(word[i] != '\0')
	{
		if(tolower(word[i]) == tolower(letter) )
			drawCharAt(word[i], x_pos, y_pos, fore_color, back_color, char_scale, video_base, table);
		x_pos+=40;
		++i;
	}
}


void draw_traces(int x_pos, int y_pos, int color, char * base, char * word)
{
	int i = 0, space = 8, length;

	while( word[i] != '\0' ) // calcula tamanho da palavra
	i++;
	length = i; // passa o tamanho para variável length

	while ( length-- != 0) // desenha espaços
	{
		draw_line(x_pos, y_pos, x_pos + 32 , y_pos, color, base);
		x_pos += 32;
		x_pos += space;
	}
}


void draw_gallow(int x_pos, int y_pos, int color, char *base)
{
	draw_line(x_pos, y_pos, x_pos, y_pos + 150, color, base); // linha da direita, vertical

	draw_line(x_pos, y_pos, x_pos - 75, y_pos, color, base); // linha horizontal
	x_pos -= 75;

	draw_line(x_pos, y_pos, x_pos, y_pos + 20, color, base); // linha da esquerda, vertical
	x_pos += 75;

	draw_line(x_pos, y_pos + 35 , x_pos - 30, y_pos, color, base); // linha diagonal
	y_pos += 150;

	draw_line(x_pos - 30, y_pos, x_pos + 30, y_pos, color, base); // baseci
}


void draw_Hangman ( int x_pos , int y_pos, int color, char * base , int num_errors )
{
	x_pos -= 75;
	y_pos += 50;
	switch(num_errors)
	{
		case 6: draw_line(x_pos + 2, y_pos - 30 + 62, x_pos + 22, y_pos - 30 + 82, color, base);
                draw_line(x_pos + 1 , y_pos - 30 + 61, x_pos + 21, y_pos - 30 + 81, color, base);
                draw_line(x_pos , y_pos - 30 + 60, x_pos + 20, y_pos - 30 + 80, color, base); // Desenha perna esquerda

		case 5: draw_line(x_pos + 2, y_pos - 30 + 62, x_pos - 22 , y_pos - 30 + 82, color, base);
                draw_line(x_pos + 1 , y_pos - 30 + 61, x_pos - 21, y_pos - 30 + 81, color, base);
                draw_line(x_pos , y_pos - 30 + 60, x_pos - 20, y_pos - 30 + 80, color, base); // Desenha perna direita

		case 4: draw_line(x_pos + 2, y_pos - 30 + 32, x_pos - 22, y_pos - 30 + 52, color, base);
                draw_line(x_pos + 1, y_pos - 30 + 31, x_pos - 21, y_pos - 30 + 51, color, base);
                draw_line(x_pos , y_pos - 30 + 30, x_pos - 20, y_pos - 30 + 50, color, base); // Desenha braço esquerdo

		case 3: draw_line(x_pos+2 , y_pos - 30 + 32, x_pos + 22, y_pos - 30 + 52, color, base);
                draw_line(x_pos+1 , y_pos - 30 + 31, x_pos + 21, y_pos - 30 + 51, color, base);
                draw_line(x_pos , y_pos - 30 + 30, x_pos + 20, y_pos - 30 + 50, color, base); // Desenha braço direiro

		case 2: draw_line(x_pos+2 , y_pos - 30 + 22, x_pos+1 , y_pos + 31, color, base);
                draw_line(x_pos+1 , y_pos - 30 + 21, x_pos+1 , y_pos + 31, color, base);
		        draw_line(x_pos , y_pos - 30 + 20, x_pos , y_pos + 30, color, base); // Desenha corpo

		case 1:	draw_circle( x_pos+2 , y_pos - 30 + 12, 10, color, base);
                draw_circle( x_pos+1 , y_pos - 30 + 11, 10, color, base);
                draw_circle( x_pos , y_pos - 30 + 10, 10, color, base); // Desenha cabeça
                //drawCharAt('.', x_pos , y_pos - 30 +10  ,FORECOLOR, BACKCOLOR, 1, base, table);   //Desenha olhos
			    break;
	}
}

int calculate_score(int num_errors, int num_letters)
{
	return (6 - num_errors)*5*num_letters;
}

void troca(Player** p1, Player** p2)
{
	Player  * aux;
	aux = *p1;
	*p1 = *p2;
	*p2 = aux;
}

void update_best_scores(Player ** best_players , Player* player)
{
	int n = 0;
	if ( best_players[0] == NULL)
	{
		best_players[0]  = player;
		best_players[1]  = NULL;
		return;
	}
	while ( best_players[n++] != NULL);
	--n;
	if ( n >= 9 )
	{
		n = 9;
		if ( best_players[n]->score < player->score  )
		{
			deletePlayer(best_players[n]);
			best_players[n] = player;
			best_players[n+1] = NULL;
		}
		else
		{
			deletePlayer(player);
			return;
		}
	}
	else
	{
		best_players[n] = player;
		best_players[n+1] = NULL;
	}

	while ( n > 0 )
	{
		if( best_players[n]->score > best_players[n-1]->score)
		{
			troca(&best_players[n], &best_players[n-1]);
		}
		--n;
	}

}

void code_key(char * string, char *table, char *base)
{
	int i = 0;
	while( string[i] != '\0' )
	{
		drawCharAt('*', 200 + i*8 , 300 , FORECOLOR, BACKCOLOR, 2, base, table);		// confirmar valores dos atributos
		i++;
	}
}

void insert_clue(char *table, char *base, SecretWord * sword)
{
	char * clue = (char *) malloc ( 60 * sizeof(char));
	int i = 0;
	char a;

	while( i < 59 )
	{
	    	a = getKey();
		if ( isalpha(a) || a == ' ' )
		{
			clue[i] = a;
			drawCharAt(clue[i] , 470 + i * 16 , 500 , FORECOLOR, BACKCOLOR, 2, base, table);
			++i;
		}
		else
			if ( a == BACKSPACE && i > 0)
			{
				--i;
				clue[i] = ' ';
				drawCharAt(clue[i] , 470 + i * 16 , 500 , FORECOLOR, BACKCOLOR, 2, base, table);
			}
			else
				if ( a == '\r' && i != 0 )
					break;
	}
	clue[i] = '\0';

	if( i >= 59 )
	{
		drawStringAt("Atingiu o limite do buffer. Carregue no Return para Continuar", 20, 550, FORECOLOR, BACKCOLOR, 2, base, table);
		while ( ( a = getKey() ) != '\r' );
		drawStringAt("                                                             ", 20, 550, FORECOLOR, BACKCOLOR, 2, base, table);
	}
	strcpy( sword->tip , clue );
}

void insert_keyword(char *table, char *base, SecretWord * sword)
{
	char * keyword = (char *) malloc ( 16 * sizeof(char));
	int i = 0;
	char a;

	while( i < 15 )
	{
	    	a = getKey();
		if ( isalpha(a) || a == ' ' )
		{
			keyword[i] = a;
			drawCharAt(keyword[i] , 470 + i * 16 , 400 , FORECOLOR, BACKCOLOR, 2, base, table);
			++i;
		}
		else
			if ( a == BACKSPACE && i > 0)
			{
				--i;
				keyword[i] = ' ';
				drawCharAt(' ' , 470 + i * 16 , 400 , FORECOLOR, BACKCOLOR, 2, base, table);
			}
			else
				if ( a == '\r' && i != 0 )
					break;
	}
	keyword[i] = '\0';

	if( i >= 15 )
	{
		drawStringAt("Atingiu o limite do buffer. Carregue no Return para Continuar", 20, 450, FORECOLOR, BACKCOLOR, 2, base, table);
		while ( ( a = getKey() ) != '\r' );
		drawStringAt("                                                             ", 20, 450, FORECOLOR, BACKCOLOR, 2, base, table);
	}
	strcpy( sword->word , keyword );
}



void print_best_scores(Player ** best_players ,  char *video_base, char *table)
{

	drawSpriteTitle( 250 , 50  , video_base );
	int i = 0;
	if ( best_players[0] == NULL  )
	{
		drawStringAt("No Best Scores Yet! ;)", 230, 220 ,  FORECOLOR, BACKCOLOR, 2, video_base, table);
		char a;
		while( ( a = getKey() ) != '\r') ;
		return;
	}

	while ( best_players[i] != NULL )
	{
		drawIntAt(i+1, i+1<10?50:34 , 200 + (i+1)*32, FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawStringAt(") ", 66, 200 + (i+1)*32 , FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawStringAt(best_players[i]->name, 98, 200 + (i+1)*32, FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawStringAt(" | ", 450, 200 + (i + 1)*32, FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawIntAt(best_players[i]->score, 580, 200 + (i+1)*32, FORECOLOR, BACKCOLOR, 2, video_base, table);
		i++;
	}
	char a;
	while( ( a = getKey() ) != '\r') ;

}

Player * setUp( char *video_base, char *table)
{
	drawStringAt("Player's name:", 200, 250, FORECOLOR, BACKCOLOR, 2, video_base, table);
	char * name = (char *) malloc ( 32 * sizeof(char));
	Player * player = (Player * )malloc( sizeof(Player) );
	int i = 0;
	char a;
	while ( i < 31)
	{
	    a = getKey();
		if ( isalpha(a) || a == ' ' )
		{
			name[i] = a;
			drawCharAt(name[i] , 440 + i * 16 , 250 , FORECOLOR, BACKCOLOR, 2, video_base, table);
			++i;
		}
		else
			if ( a == BACKSPACE && i > 0)
			{
				--i;
				name[i] = ' ';
				drawCharAt(name[i] , 440 + i * 16 , 250 , FORECOLOR, BACKCOLOR, 2, video_base, table);
			}
			else
				if ( a == '\r' && i != 0 )
					break;
		//drawIntAt(a , 470 + i * 16 , 300 , FORECOLOR, BACKCOLOR, 2, video_base, table);
	}
	name[i] = '\0';
	if ( i >= 31 )
	{
		drawStringAt("Atingiu o limite do buffer. Carrgue no Return para Continuar", 20, 450, FORECOLOR, BACKCOLOR, 2, video_base, table);
		while ( ( a = getKey() ) != '\r' );
	}
	createPlayer(player, name);
	free(name);
	return player;
}

void update_sidebar(  char *video_base, char *table )
{
	if ( ((int)(msec/1000/60))%60 < 10 )
	{
		drawCharAt( '0' , 941 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table);
		drawIntAt( ((int)(msec/1000/60))%60 , 949 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	}
	else
	  drawIntAt( ((int)(msec/1000/60))%60 , 941 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table );

	drawCharAt( ':' , 957 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table);

	if ( ((int)(msec/1000))%60 < 10 )
	{
		drawCharAt( '0' , 965 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table);
		drawIntAt( ((int)(msec/1000))%60 , 973 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	}
	else
	  drawIntAt( ((int)(msec/1000))%60 , 965 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	RTC_TIME rt;
	rtc_read_time(&rt);
	if ( rt.hour > 9 )
		drawIntAt(rt.hour , 840 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	else
	{
		drawCharAt('0' , 840 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
		drawIntAt(rt.hour , 848 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	}
	drawCharAt(':' , 856 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	if ( rt.min > 9 )
		drawIntAt( rt.min , 864 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	else
	{
		drawCharAt('0' , 864 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
		drawIntAt( rt.min , 872 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table );

	}
	drawCharAt(':' , 880 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	if ( rt.sec > 9 )
		drawIntAt( rt.sec , 888 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	else
	{
		drawCharAt('0' , 888 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
		drawIntAt( rt.sec , 896 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	}
	RTC_DATE rd;
	rtc_read_date(&rd);
	drawIntAt(rd.day , 840 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	drawCharAt('-' , 856 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawIntAt( rd.month , 864 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	drawCharAt('-' , 880 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawIntAt( 2000 + rd.year , 888 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table );
}

void drawAlpahabet( char *video_base, char *table )
{
	char a = 'A';
	int j = 1;
	drawCharAt( a++ ,  5 , 695 , FORECOLOR , BACKCOLOR, 3, video_base, table);
	while( j < 26)
	{
		drawCharAt( a,  j * 30 + 5 , 693 , FORECOLOR , BACKCOLOR, 3, video_base, table);
		draw_line( j * 30 , 690, j * 30, 740, FORECOLOR , video_base);
		++j;
		++a;
	}
	draw_line( 0 , 690, 780, 690, FORECOLOR , video_base);
    draw_line( 0 , 740, 780, 740, FORECOLOR , video_base);
}

void updateAlphabet( char * letters_used , char *video_base, char *table )
{
	int i = 0;
	while ( letters_used[++i] != '\0' );
	--i;
	int j = letters_used[i] - 'A';
	drawBox(  j * 30 , 690 , ( j +1 )* 30 , 740 ,  FORECOLOR ,  1 ,  video_base );
	drawCharAt( letters_used[i] ,  j * 30 + 5 , 693 , BACKCOLOR , FORECOLOR ,
								3, video_base, table);
}

void play_single( char *video_base, char *table , Player ** bestPlayers)
{
	int errors = 0 , right_letters = 0 ,letters = 0 , i = 0, n = 0;
	char a;
	char * letters_used = (char *) malloc ( 27 * sizeof(char));
	Note notes[] = {{Sol6, 100}, {Mi6,50}, {Sol6, 50}, {Mi6, 25}};
  	Song s = { sizeof(notes)/sizeof(Note), 10, notes};

	while( n < 27)
	{
		letters_used[n]= '\0';
		n++;
	}

	drawSpriteTitle( 250 , 50  , video_base );
	Player * player = setUp(video_base, table);
	SecretWord word = generate_string( dictionary );

	clear_screen(BACKCOLOR, video_base);
	drawSpriteTitle( 170 , 50  , video_base );
	draw_line( 780 , 0, 780, VRES, FORECOLOR , video_base);
	draw_line( 785 , 0, 785, VRES, FORECOLOR , video_base);
	drawStringAt("Date:", 800 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawStringAt("Time:", 800 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	update_sidebar(video_base , table);
	drawStringAt("Player's Name:", 800 , 150 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawStringAt(player->name, 800 , 170 , FORECOLOR, BACKCOLOR, 1, video_base, table);
 	drawStringAt("Score:", 800 , 200 , FORECOLOR, BACKCOLOR, 1, video_base, table);
 	drawIntAt(calculate_score(errors , strlen(word.word)) , 850 , 200 , FORECOLOR, BACKCOLOR, 1, video_base, table );
    drawStringAt("Time Playing:", 800 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table);

	/*Desenhar abecedário */
	drawAlpahabet( video_base, table );

  	drawStringAt("Clue:", 100, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);
	drawStringAt(word.tip, 200, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);
	draw_traces( 100  , 550 , FORECOLOR , video_base, word.word);
	draw_gallow(600  , 400 , FORECOLOR , video_base);

	msec = 0;

	do{
		while ( !hasKey() )
		  update_sidebar(video_base , table);
		update_sidebar(video_base , table );
		while ( !isalpha(a = getKey() ) )
		{
			if ( a == ESC )
			{
				clear_screen(BACKCOLOR, video_base);
				deletePlayer(player);
				return;
			}
			update_sidebar(video_base , table );
		}
		drawStringAt("Letter:", 100, 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawCharAt( ' ' , 216 , 300 , FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawCharAt( toupper(a) , 216 , 300 , FORECOLOR, BACKCOLOR, 2, video_base, table);
		updateAlphabet( letters_used ,video_base,table );
		if ( ( right_letters = find_letter(word.word, tolower(a),letters_used ) ) > 0)
		{
			update_word (100, 507, FORECOLOR, BACKCOLOR,3,video_base, table, word.word , tolower(a) );
			drawStringAt( "                    " , 100, 350, FORECOLOR, BACKCOLOR, 2, video_base, table);
			draw_traces( 100  , 550 , FORECOLOR , video_base, word.word);
			letters += right_letters;
			letters_used[i++] = toupper(a);
			updateAlphabet( letters_used ,video_base,table );

		}
		else if ( right_letters == -1)
		{
			play_note(&(s.notes[0]));
			drawStringAt("Letter already used!", 100, 350, FORECOLOR, BACKCOLOR,
							2, video_base, table);
		}
		else
		{
			++errors;
			draw_Hangman (600 , 400, FORECOLOR, video_base , errors );
			letters_used[i++] = toupper(a);
			updateAlphabet( letters_used ,video_base,table );
			drawStringAt( "                    " , 100, 350, FORECOLOR, BACKCOLOR, 2, video_base, table);
		    drawStringAt("                    ", 850 , 200 , FORECOLOR, BACKCOLOR,
							1, video_base, table );
			drawIntAt(calculate_score(errors , strlen(word.word)) , 850 , 200 ,
							FORECOLOR, BACKCOLOR, 1, video_base, table );
		}
		if ( letters >= strlen(word.word) )
		{
			clear_screen(BACKCOLOR, video_base);
			play_song(&s);
			drawCharAt( 3 , 250 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			drawCharAt( 3 , 300 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);

			drawStringAt("You Won", 350, 270, FORECOLOR, BACKCOLOR, 2, video_base, table);
			drawCharAt( 3 , 480 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			drawCharAt( 3 , 530 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			while( ( a = getKey() ) != '\r') ;
			player->score = calculate_score(errors , strlen(word.word));
			update_best_scores(bestPlayers, player);
			free(letters_used);
			clear_screen(BACKCOLOR, video_base);
			return;
		}
	}while (errors < 6);
	player->score = calculate_score(errors , strlen(word.word));
	clear_screen(BACKCOLOR, video_base);
	drawStringAt("Loser! =(", 300, 250, FORECOLOR, BACKCOLOR, 2, video_base, table);
	while( ( a = getKey() ) != '\r') ;
	clear_screen(BACKCOLOR, video_base);
	free(letters_used);
	deletePlayer(player);
}

void play_client( Word base , char *video_base, char *table , Player ** bestPlayers)
{
	cleanUART( base );
	int errors = 0 , right_letters = 0 ,letters = 0 ;
	Note notes[] = {{Sol6, 100}, {Mi6,50}, {Sol6, 50}, {Mi6, 25}};
  	Song s = { sizeof(notes)/sizeof(Note), 10, notes};

	char * letters_used = (char *) malloc ( 27 * sizeof(char));
	int n = 0;
	while( n < 27)
	{
		letters_used[n]= '\0';
		n++;
	}

	SecretWord word;
	clear_screen(BACKCOLOR, video_base);
	drawSpriteTitle( 250 , 50  , video_base );
	Player * player1 = setUp(video_base, table);
	sync_unlock( base );
	send_string(base , player1->name);
	clear_screen(BACKCOLOR, video_base);
	drawSpriteTitle( 250 , 50  , video_base );

	Player * player2 = ( Player * )malloc(sizeof(Player));

	drawStringAt("Waiting for the other player..", 100, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);
	
	int i  = 0;

	char * string = (char*) malloc(32 * sizeof(char));
	sync_lock( base );
	while( ( string[i++]  = rcv_char(base) ) != '\0' && i < 31 )
	string[i] = '\0';
	createPlayer( player2 , string );
	drawStringAt("Received:", 100, 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
	drawStringAt(player2->name, 260 , 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
	drawStringAt("Waiting for the word...", 100, 400, FORECOLOR, BACKCOLOR, 2, video_base, table);
  	i = 0;
	free(string);
	string = (char*) malloc(16 * sizeof(char));

	sync_lock( base );
	while( ( string[i++]  = rcv_char(base) ) != '\0' && i < 15 )
	string[i] = '\0';
	strcpy( word.word ,  string );


	drawStringAt("Waiting for the tip...", 100, 500, FORECOLOR, BACKCOLOR, 2, video_base, table);
	i = 0;
	free(string);
	string = (char*) malloc(64 * sizeof(char));
	sync_lock( base );
	while( ( string[i++]  = rcv_char(base) ) != '\0' && i < 63 )
	string[i] = '\0';
	strcpy( word.tip , string );

	free(string);
	string = NULL;

	clear_screen(BACKCOLOR, video_base);
	drawSpriteTitle( 170 , 50  , video_base );
	draw_line( 780 , 0, 780, VRES, FORECOLOR , video_base);
	draw_line( 785 , 0, 785, VRES, FORECOLOR , video_base);
	drawStringAt("Date:", 800 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawStringAt("Time:", 800 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	update_sidebar(video_base , table);
	drawStringAt("Player's Name:", 800 , 150 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawStringAt(player1->name, 800 , 170 , FORECOLOR, BACKCOLOR, 1, video_base, table);
 	drawStringAt("Score:", 800 , 200 , FORECOLOR, BACKCOLOR, 1, video_base, table);
 	drawIntAt(calculate_score(errors , strlen(word.word)) , 850 , 200 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	drawStringAt("Time Playing:", 800 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table);

	drawAlpahabet( video_base, table );

  	drawStringAt("Clue:", 100, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);
	drawStringAt(word.tip, 200, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);
	draw_traces( 100  , 550 , FORECOLOR , video_base, word.word);
	draw_gallow(600  , 400 , FORECOLOR , video_base);

	i = 0;
	char a;
	msec = 0;

	do{
		while ( !hasKey() )
			update_sidebar(video_base , table);
		send_char(base , a);
		update_sidebar(video_base , table );
		while ( !isalpha(a = getKey() ) )
			if ( a == ESC )
			{
				send_char(base , a);
				clear_screen(BACKCOLOR, video_base);
				deletePlayer(player1);
				deletePlayer(player2);
				return;
			}
		send_char(base , a);
		drawStringAt("Letter:", 100, 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawCharAt( ' ' , 216 , 300 , FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawCharAt( toupper(a) , 216 , 300 , FORECOLOR, BACKCOLOR, 2, video_base, table);

		if ( ( right_letters = find_letter(word.word, tolower(a),letters_used ) ) > 0)
		{
			drawStringAt( "                    " , 100, 350, FORECOLOR, BACKCOLOR, 2, video_base, table);
			update_word (100, 507, FORECOLOR, BACKCOLOR,3,video_base, table, word.word , tolower(a) );
			draw_traces( 100  , 550 , FORECOLOR , video_base, word.word);
			letters += right_letters;
			letters_used[i++] = toupper(a);
			updateAlphabet( letters_used ,video_base,table );

		}
		else if ( right_letters == -1)
			{
				play_note(&(s.notes[0]));
				drawStringAt("Letter already used!", 100, 350, FORECOLOR, BACKCOLOR, 2, video_base, table);
			}
			else
			{
				++errors;
				draw_Hangman (600 , 400, FORECOLOR, video_base , errors);
				letters_used[i++] = toupper(a);
				updateAlphabet( letters_used ,video_base,table );
			}

		if ( letters >= strlen(word.word) )
		{
			play_song(&s);
			clear_screen(BACKCOLOR, video_base);
			drawSpriteTitle( 250 , 50  , video_base );
			drawCharAt( 3 , 250 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			drawCharAt( 3 , 300 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);

			drawStringAt("You Won", 350, 270, FORECOLOR, BACKCOLOR, 2, video_base, table);
			drawCharAt( 3 , 480 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			drawCharAt( 3 , 530 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			player1->score = calculate_score(errors , strlen(word.word));
			while(!hasKey());
			getKey();
			clear_screen(BACKCOLOR, video_base);
			update_best_scores(bestPlayers, player1);
			deletePlayer(player2);
			return;
		}

	}while (errors < 6);
	clear_screen(BACKCOLOR, video_base);
	drawSpriteTitle( 250 , 50  , video_base );
	drawStringAt("Loser! =(", 300, 250, FORECOLOR, BACKCOLOR, 2, video_base, table);
	while(!hasKey());
	getKey();
	clear_screen(BACKCOLOR, video_base);
	deletePlayer(player1);
	deletePlayer(player2);
}

void play_server(Word base ,  char *video_base, char *table , Player ** bestPlayers )
{
	cleanUART( base );
	SecretWord word;
	int errors = 0 , right_letters = 0 ,letters = 0;

	Note notes[] = {{Sol6, 100}, {Mi6,50}, {Sol6, 50}, {Mi6, 25}};
  	Song s = { sizeof(notes)/sizeof(Note), 10, notes};

	char * letters_used = (char *) malloc ( 27 * sizeof(char));
	int n = 0;
	while( n < 27)
	{
		letters_used[n]= '\0';
		n++;
	}
	drawSpriteTitle( 250 , 50  , video_base );
	Player * player1 = setUp(video_base, table);

	Player * player2 = ( Player * )malloc(sizeof(Player));
	player2->score = 0;
	clear_screen(BACKCOLOR, video_base);
	drawStringAt("Waiting for the other player..." , 100, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);

	int i  = 0;
	char * string = (char*) malloc(64 * sizeof(char));
	sync_lock( base );
	while( ( string[i++] = rcv_char(base) ) != '\0' );
	string[i]='\0';
	player2->name = string;
	drawStringAt("Received:", 100, 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
	drawStringAt(player2->name, 260 , 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
	sync_unlock( base );
	send_string( base , player1->name);

	drawStringAt("Insert the keyword:" , 100, 400, FORECOLOR, BACKCOLOR, 2, video_base, table);
	insert_keyword(table, video_base, &word);	// imprimir no ecră a palavra-chave
	sync_unlock( base );
	send_string(base , word.word);

	drawStringAt("Insert the tip:", 100, 500, FORECOLOR, BACKCOLOR, 2, video_base, table);
	insert_clue(table, video_base, &word);		// imprimir dica normalmente
	sync_unlock( base );
	send_string(base , word.tip);

	clear_screen(BACKCOLOR, video_base);
	drawSpriteTitle( 170 , 50  , video_base );
	draw_line( 780 , 0, 780, VRES, FORECOLOR , video_base);
	draw_line( 785 , 0, 785, VRES, FORECOLOR , video_base);
	drawStringAt("Date:", 800 , 40 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawStringAt("Time:", 800 , 60 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	update_sidebar(video_base , table);
	drawStringAt("Player's Name:", 800 , 150 , FORECOLOR, BACKCOLOR, 1, video_base, table);
	drawStringAt(player2->name, 800 , 170 , FORECOLOR, BACKCOLOR, 1, video_base, table);
 	drawStringAt("Score:", 800 , 200 , FORECOLOR, BACKCOLOR, 1, video_base, table);
 	drawIntAt(calculate_score(errors , strlen(word.word)) , 850 , 200 , FORECOLOR, BACKCOLOR, 1, video_base, table );
	drawStringAt("Time Playing:", 800 , 240 , FORECOLOR, BACKCOLOR, 1, video_base, table);

	drawAlpahabet( video_base, table );

  	drawStringAt("Clue:", 100, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);
	drawStringAt(word.tip, 200, 200, FORECOLOR, BACKCOLOR, 2, video_base, table);
	draw_traces( 100  , 550 , FORECOLOR , video_base, word.word);
	draw_gallow(600  , 400 , FORECOLOR , video_base);

	drawAlpahabet( video_base, table );

	i = 0;
	char a;
	msec = 0;
	do{
		while ( !char_available(base) )
		{
			update_sidebar(video_base , table );
			if ( hasKey() )
				if ( getKey() == ESC )
				{
					clear_screen(BACKCOLOR, video_base);
					deletePlayer(player1);
					deletePlayer(player2);
					return;
				}
		}
		update_sidebar(video_base , table );
		while ( !isalpha( a = rcv_char(base) ) )
			if ( a == ESC )
			{
				clear_screen(BACKCOLOR, video_base);
				drawStringAt("Client Disconnected..", 100, 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
				while(!hasKey());
				getKey();
				deletePlayer(player1);
				deletePlayer(player2);
				clear_screen(BACKCOLOR, video_base);
				return;
			}

		drawStringAt("Letter:", 100, 300, FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawCharAt( ' ' , 216 , 300 , FORECOLOR, BACKCOLOR, 2, video_base, table);
		drawCharAt( toupper(a) , 216 , 300 , FORECOLOR, BACKCOLOR, 2, video_base, table);

		if ( ( right_letters = find_letter(word.word, tolower(a),letters_used ) ) > 0)
		{
			drawStringAt( "                    " , 100, 350, FORECOLOR, BACKCOLOR, 2, video_base, table);
			update_word (100, 507, FORECOLOR, BACKCOLOR,3,video_base, table, word.word , tolower(a) );
			draw_traces( 100  , 550 , FORECOLOR , video_base, word.word);
			letters += right_letters;
			letters_used[i++] = toupper(a);
			updateAlphabet( letters_used ,video_base,table );
		}
		else if ( right_letters == -1)
			{
				drawStringAt("Letter already used!", 100, 350, FORECOLOR, BACKCOLOR, 2, video_base, table);
			}
			else
			{
				++errors;
				draw_Hangman (600 , 400, FORECOLOR, video_base , errors );
				letters_used[i++] = toupper(a);
				updateAlphabet( letters_used ,video_base,table );
			}

		if ( letters >= strlen(word.word) )
		{
			play_song(&s);
			clear_screen(BACKCOLOR, video_base);
			drawSpriteTitle( 250 , 50  , video_base );
			drawCharAt( 3 , 250 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			drawCharAt( 3 , 300 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			player2->score = calculate_score(errors , strlen(word.word));
			update_best_scores(bestPlayers, player2);
			drawStringAt("He Won!", 350, 270, FORECOLOR, BACKCOLOR, 2, video_base, table);
			drawCharAt( 3 , 480 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			drawCharAt( 3 , 530 , 250 , FORECOLOR, BACKCOLOR, 5, video_base, table);
			while(!hasKey());
			getKey();
			clear_screen(BACKCOLOR, video_base);
			deletePlayer(player1);
			return;
		}

	}while (errors < 6);
	clear_screen(BACKCOLOR, video_base);
	drawSpriteTitle( 250 , 50  , video_base );
	drawStringAt("The other player is a LOSER!", 300, 250, FORECOLOR, BACKCOLOR, 2, video_base, table);
	while(!hasKey());
	getKey();
	clear_screen(BACKCOLOR, video_base);
	deletePlayer(player1);
	deletePlayer(player2);
}

Bool sync_server(Word base ,  char *video_base, char *table)
{
	cleanUART( base );
	drawStringAt("Waiting for a client...", 300, 250, FORECOLOR, BACKCOLOR, 2, video_base, table);
	char a = rcv_char(base);
	if ( a == 'r' )
		send_char(base, 'a');
	else
		return false;
	return true;
}

Bool sync_client(Word base ,  char *video_base, char *table)
{
	cleanUART( base );
	send_char(base, 'r');
	drawStringAt("Attempting to connect...", 300, 250, FORECOLOR, BACKCOLOR, 2, video_base, table);
	int timeout = msec + 10000 , previous = msec;
	while ( msec < timeout )
		if ( char_available(base) )
		{
			if ( rcv_char(base) == 'a' )
				return true;
			else
				return false;
		}
		else
			if ( ( msec - previous ) > 1000)
			{
				previous = msec;
				send_char(base, 'r');
			}
	return false;
}

void showManual( char *video_base, char *table)
{
    clear_screen(BACKCOLOR, video_base);
    drawSpriteTitle( 250 , 50  , video_base );
    drawStringAt("Hangman is a tradicional game that can be played by one or two players.", 230, 200 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("By choosing the 'Play' mode, the use can choose between 'One Player',", 230, 230 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("where he tries to guess the word generated by the computer, 'Two", 230, 260 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("Players - Server', where he chooses a word and a tip so that the", 230, 290 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("other player can try to guess the keyword, and 'Two Players - Client',", 230, 320 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("where he tries to guess the correct word entered by the other player.", 230, 350 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("Like the original game, the player can only fail 6 times. If he guesses", 230, 380 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("the word, he wins and he is awarded with points that depend on the number", 230, 410 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("of letters of the keyword and on the number of errors. But, if he doesn't", 230, 440 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("guess the word before he fails 6 times, he loses and, in the 'Two Players'", 230, 470 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("mode, the other player gets the points. When the player bets a letter that", 230, 500 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("doesn't belong in the word, a part of the hangman is drawn. If he bets on", 230, 530 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("a letter that he already guessed before, a error message is shown and a", 230, 560 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("sound is heard. Sounds are also heard when a player beats the game.", 230, 590 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("The user can also check the high-scores in the 'Scores' mode and read", 230, 620 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("the instructions in the 'Manual' mode.", 230, 650 ,  FORECOLOR, BACKCOLOR, 1, video_base, table);
    drawStringAt("Have fun!!!", 430, 680 ,  FORECOLOR, BACKCOLOR, 2, video_base, table);
    char a;
    while( ( a = getKey() ) != '\r') ;
    return;

}
